﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Workflow.Runtime.Tracking;
using System.Workflow.ComponentModel;
using BneyBaruch.Ingest.Core.ServiceModel;
using System.ServiceModel;

namespace BneyBaruch.Ingest.Core.WorkflowCommunication.Tracking
{
    public class WorkflowMonitoringTrackingService : TrackingService
    {
        #region Fields

        private IWorkflowTrackingService workflowTrackingService = null;
        private ServiceHost workflowTrackingServiceHost = null;

        #endregion

        protected override void OnStarted()
        {
            base.OnStarted();
            workflowTrackingService = new WorkflowTrackingService();
            workflowTrackingServiceHost = new ServiceHost(workflowTrackingService);
            workflowTrackingServiceHost.Open();
        }

        protected override void OnStopped()
        {
            base.OnStopped();
            try
            {
                workflowTrackingServiceHost.Close();
            }
            catch
            {
                if (workflowTrackingServiceHost.State == CommunicationState.Faulted)
                    workflowTrackingServiceHost.Abort();
            }
        }

        #region TrackingService Overrides

        protected override TrackingProfile GetProfile(Guid workflowInstanceId)
        {
            // Does not support reloading/instance profiles
            throw new NotImplementedException("The method or operation is not implemented.");
        }

        protected override TrackingProfile GetProfile(Type workflowType, Version profileVersionId)
        {            
            // Return the version of the tracking profile that runtime requests (profileVersionId)
            return GetProfile();
        }

        protected override TrackingChannel GetTrackingChannel(TrackingParameters parameters)
        {
            return new WorkflowMonitoringTrackingChannel(workflowTrackingService, parameters);
        }

        protected override bool TryGetProfile(Type workflowType, out TrackingProfile profile)
        {
            //Depending on the workflowType, service can return different tracking profiles
            //In this sample we're returning the same profile for all running types
            profile = GetProfile();
            return true;
        }

        protected override bool TryReloadProfile(Type workflowType, Guid workflowInstanceId, out TrackingProfile profile)
        {
            // Returning false to indicate there is no new profiles
            profile = null;
            return false;
        }

        #endregion

        #region GetProfile Private Method

        // Profile creation
        private static TrackingProfile GetProfile()
        {
            // Create a Tracking Profile
            TrackingProfile profile = new TrackingProfile();
            profile.Version = new Version("3.0.0");

            // Add a TrackPoint to cover all activity status events
            ActivityTrackPoint activityTrackPoint = new ActivityTrackPoint();
            ActivityTrackingLocation activityLocation = new ActivityTrackingLocation(typeof(Activity));
            activityLocation.MatchDerivedTypes = true;
            WorkflowTrackingLocation wLocation = new WorkflowTrackingLocation();

            IEnumerable<ActivityExecutionStatus> statuses = Enum.GetValues(typeof(ActivityExecutionStatus)) as IEnumerable<ActivityExecutionStatus>;
            foreach (ActivityExecutionStatus status in statuses)
            {
                activityLocation.ExecutionStatusEvents.Add(status);
            }

            activityTrackPoint.MatchingLocations.Add(activityLocation);
            profile.ActivityTrackPoints.Add(activityTrackPoint);

            // Add a TrackPoint to cover all workflow status events
            WorkflowTrackPoint workflowTrackPoint = new WorkflowTrackPoint();
            workflowTrackPoint.MatchingLocation = new WorkflowTrackingLocation();
            foreach (TrackingWorkflowEvent workflowEvent in Enum.GetValues(typeof(TrackingWorkflowEvent)))
            {
                workflowTrackPoint.MatchingLocation.Events.Add(workflowEvent);
            }
            profile.WorkflowTrackPoints.Add(workflowTrackPoint);

            // Add a TrackPoint to cover all user track points
            UserTrackPoint userTrackPoint = new UserTrackPoint();
            UserTrackingLocation userLocation = new UserTrackingLocation();
            userLocation.ActivityType = typeof(Activity);
            userLocation.MatchDerivedActivityTypes = true;
            userLocation.ArgumentType = typeof(object);
            userLocation.MatchDerivedArgumentTypes = true;
            userTrackPoint.MatchingLocations.Add(userLocation);
            profile.UserTrackPoints.Add(userTrackPoint);

            return profile;
        }

        #endregion
    }
}
